package com.beemans.corekit.integration.admob;

import android.content.Context;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdLoader;
import com.google.android.gms.ads.LoadAdError;
import com.google.android.gms.ads.ResponseInfo;
import com.google.android.gms.ads.admanager.AdManagerAdRequest;
import com.google.android.gms.ads.nativead.NativeAd;

public class AbNativeAdWrapper {
    @NonNull
    private final String placementId;
    @Nullable
    private NativeAd mNativeAd;
    @Nullable
    private AbAdEventListener mEventListener;
    @Nullable
    private AbAdNetworkListener mNetworkListener;

    private boolean isLoadingAd = false;
    private boolean isAdPreviewed = false;

    public AbNativeAdWrapper(@NonNull String placementId) {
        this.placementId = placementId;
    }

    @NonNull
    public String getPlacementId() {
        return placementId;
    }

    public boolean isAdvertReady() {
        return mNativeAd != null && !isAdPreviewed;
    }

    public boolean isAdvertLoading() {
        return isLoadingAd;
    }

    public void loadAd(
            @NonNull Context context,
            @NonNull AbAdNetworkListener networkListener
    ) {
        isLoadingAd = true;
        mNetworkListener = networkListener;

        AbAdvertLoadManager.getInstance().updateNativeLoadingList(this, false);

        try {
            final AdLoader.Builder builder = getBuilder(context);
            final AdLoader adLoader = getAdLoader(builder);
            final AdManagerAdRequest request = new AdManagerAdRequest.Builder().build();
            adLoader.loadAd(request);
        } catch (Throwable throwable) {
            isLoadingAd = false;
            mNetworkListener = null;

            onAdvertLoadComplete();
            handleAdFailedToLoad(networkListener, throwable.getMessage());
        }
    }

    public void showAd(
            @NonNull ViewGroup advertContainer,
            @NonNull AbAdEventListener eventListener,
            @NonNull IAbNativeSelfRender nativeSelfRender
    ) {
        AbAdvertLoadManager.getInstance().updateNativeReadyList(this, true);

        if (mNativeAd == null) {
            handleAdDisplayFailed(eventListener, "");
            return;
        }

        isAdPreviewed = true;
        mEventListener = eventListener;

        try {
            nativeSelfRender.onBindView(mNativeAd, v -> onAdvertClosed());

            advertContainer.removeAllViews();
            advertContainer.addView(nativeSelfRender.getSelfRenderView());
        } catch (Throwable throwable) {
            isAdPreviewed = false;
            mEventListener = null;

            handleAdDisplayFailed(eventListener, throwable.getMessage());
        }
    }

    public void destroy() {
        mNetworkListener = null;
        mEventListener = null;

        if (isAdPreviewed && mNativeAd != null) {
            try {
                mNativeAd.destroy();
            } catch (Throwable ignored) {
            }
            mNativeAd = null;
        }
    }

    private void onAdvertClosed() {
        if (mEventListener != null) {
            mEventListener.onAdClosed(getResponseInfo());
        }
    }

    private void handleAdDisplayFailed(
            @Nullable AbAdEventListener eventListener,
            @Nullable String adError
    ) {
        if (eventListener != null) {
            eventListener.onAdDisplayFailed(adError);
        }
    }

    private void handleAdFailedToLoad(
            @Nullable AbAdNetworkListener networkListener,
            @Nullable String loadAdError
    ) {
        if (networkListener != null) {
            networkListener.onAdFailedToLoad(loadAdError);
        }
    }

    private void onAdvertLoadComplete() {
        AbAdvertLoadManager.getInstance().updateNativeLoadingList(this, true);
    }

    @NonNull
    private AdLoader.Builder getBuilder(@NonNull Context context) {
        final AdLoader.Builder builder = new AdLoader.Builder(context, placementId);
        builder.forNativeAd(nativeAd -> {
            isLoadingAd = false;
            onAdvertLoadComplete();

            AbAdvertLoadManager.getInstance().updateNativeReadyList(this, false);

            if (mNativeAd != null) {
                try {
                    mNativeAd.destroy();
                } catch (Throwable ignored) {
                }
            }

            mNativeAd = nativeAd;

            nativeAd.setOnPaidEventListener(adValue -> {
                if (mEventListener != null) {
                    mEventListener.onAdPaidEvent(getResponseInfo(), adValue);
                }
            });

            if (mNetworkListener != null) {
                mNetworkListener.onAdLoaded();
            }
        });
        return builder;
    }

    @NonNull
    private AdLoader getAdLoader(@NonNull AdLoader.Builder builder) {
        return builder.withAdListener(new AdListener() {
            @Override
            public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
                isLoadingAd = false;

                onAdvertLoadComplete();
                handleAdFailedToLoad(mNetworkListener, loadAdError.toString());
            }

            @Override
            public void onAdImpression() {
                if (mEventListener != null) {
                    mEventListener.onAdImpression(getResponseInfo());
                }
            }

            @Override
            public void onAdClicked() {
                if (mEventListener != null) {
                    mEventListener.onAdClicked(getResponseInfo());
                }
            }

            // 点击广告回切应用回来后会自动触发关闭回调，有毛病
            @Override
            public void onAdClosed() {
            }

            @Override
            public void onAdOpened() {
            }

            @Override
            public void onAdSwipeGestureClicked() {
            }
        }).build();
    }

    @Nullable
    private ResponseInfo getResponseInfo() {
        return mNativeAd != null ? mNativeAd.getResponseInfo() : null;
    }
}